package com.oplink.webems.modules.alarm.service;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Random;

import net.sf.ehcache.hibernate.HibernateUtil;

import org.apache.commons.lang3.StringUtils;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Restrictions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.fastjson.JSONObject;
import com.oplink.webems.common.persistence.Page;
import com.oplink.webems.common.snmp.base.SnmpException;
import com.oplink.webems.common.snmp.entity.SccCard;
import com.oplink.webems.common.snmp.service.SnmpService;
import com.oplink.webems.common.utils.DateUtils;
import com.oplink.webems.modules.alarm.dao.AlarmCurrentDao;
import com.oplink.webems.modules.alarm.dao.AlarmOpsmModeDao;
import com.oplink.webems.modules.alarm.dao.AlarmPropDao;
import com.oplink.webems.modules.alarm.dao.AlarmSeverDao;
import com.oplink.webems.modules.alarm.dao.AlarmStatusDao;
import com.oplink.webems.modules.alarm.dao.AlarmTypeDao;
import com.oplink.webems.modules.alarm.dao.TrapTypeDao;
import com.oplink.webems.modules.alarm.entity.AlarmCurrent;
import com.oplink.webems.modules.alarm.entity.AlarmOpsmMode;
import com.oplink.webems.modules.alarm.entity.AlarmProp;
import com.oplink.webems.modules.alarm.entity.AlarmSeverity;
import com.oplink.webems.modules.alarm.entity.AlarmType;
import com.oplink.webems.modules.alarm.entity.TrapOid;
import com.oplink.webems.modules.alarm.entity.TrapParam;
import com.oplink.webems.modules.alarm.entity.TrapType;
import com.oplink.webems.modules.alarm.service.anno.AnalysisChild;
import com.oplink.webems.modules.alarm.service.anno.AnalysisParent;
import com.oplink.webems.modules.alarm.service.anno.GetFieldAnno;
import com.oplink.webems.modules.cfg.dao.CfgNeDao;
import com.oplink.webems.modules.cfg.dao.CfgSlotDao;
import com.oplink.webems.modules.cfg.entity.CfgCard;
import com.oplink.webems.modules.cfg.entity.CfgNe;
import com.oplink.webems.modules.cfg.entity.CfgSlot;

/**
 * Current Alarm Service
 * @author yizhang
 * @param <T>
 */
@Component
@Transactional
public class AlarmCurrentService {

	@SuppressWarnings("unused")
	private static Logger logger = LoggerFactory.getLogger(AlarmCurrentService.class);

	@Autowired
	private AlarmCurrentDao alarmcurrentDao;

	@Autowired
	private CfgSlotDao slotDao;
	
	@Autowired
	private TrapTypeDao traptypeDao;

	@Autowired
	private CfgNeDao neDao;

	@Autowired
	private AlarmTypeDao alarmtypeDao;

	@Autowired
	private AlarmSeverDao alarmseverDao;

	@Autowired
	private AlarmOpsmModeDao alarmopsmmodeDao;
	
	@Autowired
	private AlarmPropDao alarmpropDao;
	
	@Autowired
	private AlarmStatusDao statusDao;
	
	@Autowired
	private SnmpService snmpService;
	
	/**
	 * 当前告警查询
	 * @param page
	 * @param alarmCurrent
	 * @return
	 */
	public Page<AlarmCurrent> find(Page<AlarmCurrent> page, AlarmCurrent alarmCurrent) {
		DetachedCriteria dc = alarmcurrentDao.createDetachedCriteria();
		if (alarmCurrent.getNenode() != null) {
			if (alarmCurrent.getNenode().getSite() != null) {
				if (alarmCurrent.getNenode().getSite().getSid() != 0) {
				  dc.createCriteria("nenode").add(Restrictions.eq("site.sid", alarmCurrent.getNenode().getSite().getSid()));
				}				
			}
			//if (alarmCurrent.getNenode().getIp() != null) {
				if (alarmCurrent.getNenode().getNid() != 0) {
				  dc.add(Restrictions.eq("nenode.nid", alarmCurrent.getNenode().getNid()));
				}	
			//}
		}
		if (alarmCurrent.getSlot() != null) {
			if (alarmCurrent.getSlot().getSlotid() != 0) {
			  dc.add(Restrictions.eq("slot.slotid", alarmCurrent.getSlot().getSlotid()));
			}		
		}		
		if (alarmCurrent.getSeverity() != null) {
			if (alarmCurrent.getSeverity().getId() != 0) {
			  dc.add(Restrictions.eq("severity.id", alarmCurrent.getSeverity().getId()));
			}		
		}		
		if (alarmCurrent.getAtype() != null) {
			if (alarmCurrent.getAtype().getAid() != 0) {
			  dc.add(Restrictions.eq("atype.aid", alarmCurrent.getAtype().getAid()));
			}		
		}		
		return alarmcurrentDao.find(page, dc);
	}	

	/**
	 * 解析Trap上报的当前告警信息，存数据库
	 */
	@SuppressWarnings({ "rawtypes", "unchecked" })
	public AlarmCurrent currentAlarmOper(Map<String, String> trapmap) {
		AnalysisParent c = new AnalysisChild();
		AlarmCurrent acur = new AlarmCurrent();
		List<GetFieldAnno> list = c.init();// 获取泛型中类里面的注解
		String toid = trapmap.get("1.3.6.1.6.3.1.1.4.1.0");
		List<TrapOid> plist = alarmcurrentDao.findByOid(toid);
		TrapOid tobj = null;
		String val = "";
		if ((plist != null) && (plist.size() > 0)) {
			tobj = plist.get(0);
			List<TrapParam> tplist = tobj.getPlist();
			try {
				for (Iterator<TrapParam> it = tplist.iterator(); it.hasNext();) {
					TrapParam obj = (TrapParam) it.next();
					val = trapmap.get(obj.getParamoid());
					for (GetFieldAnno l : list) {
						if (!l.getMeta().oid().equals("")) {
							if (l.getMeta().oid().indexOf(obj.getParamoid().trim()) != -1) {
								if (l.getType() == String.class) {
									acur.getClass().getMethod("set".concat(getMethodName(l.getName())), String.class).invoke(acur, new Object[] { val });
								}
								if (l.getType() == Date.class) {
									Date adate = DateUtils.getStringDate(val, "yyyy-MM-dd HH:mm:ss");
									acur.getClass().getMethod("set".concat(getMethodName(l.getName())), Date.class).invoke(acur, new Object[] { adate });
								}
								if (l.getType() == int.class) {
									acur.getClass().getMethod("set".concat(getMethodName(l.getName())), int.class).invoke(acur, new Object[] { Integer.parseInt(val) });
								}
								if (l.getType() == CfgSlot.class) {
									CfgSlot slot = slotDao.findOne(Long.parseLong(val));
									acur.setSlot(slot);
								}
								if (l.getType() == TrapType.class) {
									List<TrapType> typelist = traptypeDao.findOneType(val);
									TrapType traptype = typelist.get(0);
									acur.setTraptype(traptype);
								}
								if (l.getType() == AlarmType.class) {
									AlarmType atype = alarmtypeDao.findOne(Long.parseLong(val));
									acur.setAtype(atype);
								}
								if (l.getType() == AlarmSeverity.class) {
									AlarmSeverity severity = alarmseverDao.findOne(Long.parseLong(val));
									acur.setSeverity(severity);
								}
								if (l.getType() == AlarmOpsmMode.class) {
									List<AlarmOpsmMode> modelist = alarmopsmmodeDao.findOneMode(val);
									AlarmOpsmMode amode = modelist.get(0);
									acur.setAmode(amode);
								}
							}
						}
					}
					// 暂时写死，底层需上报网元信息
					Iterator<CfgNe> neobjIt = neDao.findAll().iterator();
					List<CfgNe> listNe = new ArrayList<CfgNe>();
					while(neobjIt.hasNext()){
						listNe.add(neobjIt.next());
					}
					//暂时随机网元
					acur.setNenode(listNe.get(new Random().nextInt(listNe.size()-1)));
					Date sdate = DateUtils.getNowDate();
					acur.setSdate(sdate);
					acur.setSccport("1");
				}
				// AlarmCurrent scur = alarmcurrentDao.loadAlarmCurrent(acur);
				return alarmcurrentDao.save(acur);
			} catch (Exception ex) {
				ex.fillInStackTrace();
			}
		}
		return null;
	}

	/**
	 * 单条当前告警信息
	 * @param id
	 * @return
	 */
	public AlarmCurrent getAlarmCurrent(Long id) {
		AlarmCurrent acurr = alarmcurrentDao.findOne(id);
		return acurr;
	}
	
	/**
	 * 删除指定当前告警
	 * @param arr
	 */
	public void delCurRow(String[] arr) {
	  for (String idItem : arr) {
		alarmcurrentDao.delete(Long.parseLong(idItem));
		alarmcurrentDao.flush();
	  }
	}
	
	public void delCurRow1(String[] arr) {
	  for (String aid : arr) {
	    alarmcurrentDao.deleteAcur(aid);
	  }
	}
	
	/**
	 * 按区间获取当前告警
	 * @return
	 */
	public List<AlarmCurrent> getCurrentAlarm() {
		List<AlarmCurrent> alist = alarmcurrentDao.getCurrentAlarm(0, 5);
		return alist;
	}

	@SuppressWarnings("rawtypes")
	public List<Map> changeJsonList(List<AlarmCurrent> alist) {
		List<Map> jsonlist = new ArrayList<Map>();
		Map<String, Comparable> map = null;
		if (alist != null && alist.size() > 0) {
			for (Iterator<AlarmCurrent> it = alist.iterator(); it.hasNext();) {
				AlarmCurrent obj = (AlarmCurrent) it.next();
				map = new HashMap<String, Comparable>();
				map.put("severity", obj.getSeverity().getSeverity());
				map.put("traptype", obj.getTraptype().getTraptype());
				map.put("atype", obj.getAtype().getAlarmdesc());
				map.put("sname", obj.getNenode().getSite().getSname());
				map.put("ip", obj.getNenode().getIp());
				map.put("slot", obj.getSlot().getNum());
				map.put("card", obj.getSlot().getCard().getCardname());
				map.put("atime", obj.getAdate());
				map.put("slotid", obj.getSlot().getSlotid());
				map.put("nid", obj.getNenode().getNid());
				jsonlist.add(map);
			}
		}
		return jsonlist;
	}
	
	public List<AlarmProp> getAlarmProp(String aname, String cardtype) {
		DetachedCriteria dc = alarmpropDao.createDetachedCriteria();
		if (StringUtils.isNotEmpty(aname)) {
			dc.add(Restrictions.eq("aname", aname));
		}
		if (StringUtils.isNotEmpty(cardtype)) {
			dc.add(Restrictions.eq("cardtype.id", Long.parseLong(cardtype)));
		}		
		return alarmpropDao.find(dc);
	}	
	
	/**
	 * 保存同步的告警信息
	 * @param list
	 */
	public void synAlarmSave(List<Map<String, String>> list){
		Map<String, String> record = new HashMap<String, String>();
		AlarmCurrent acur = new AlarmCurrent();
		if (list != null && list.size() > 0) {
			for (int i=0;i<list.size();i++) {
				record = (Map<String, String>) list.get(i);
				if (StringUtils.isNotEmpty(record.get("otime"))){
				  Date adate = DateUtils.getStringDate(record.get("otime"), "yyyy-MM-dd HH:mm:ss");
				  acur.setAdate(adate);
				}
				if (StringUtils.isNotEmpty(record.get("slot"))){
				  acur.setSlot(slotDao.findOne(Long.parseLong(record.get("slot"))));
				}
				if (StringUtils.isNotEmpty(record.get("aname"))){
				  acur.setAid("0");
				  acur.setAidx("0");
				  List<AlarmProp> aprop = getAlarmProp(record.get("aname"), "1");
				  if (aprop!=null && aprop.size()>0){
					  acur.setAtype(aprop.get(0).getAlarmtype()); 
					  acur.setSeverity(aprop.get(0).getSeverity()); 
				  }
				}				
				  acur.setChassis(1);
				  acur.setPort(1);
				  acur.setPosition("chassis id = 1; slot id = ".concat(record.get("slot")).concat("; port id = 1"));
				  acur.setSccport("1");
				  acur.setAmode(alarmopsmmodeDao.findOne((long)1));
				  acur.setTraptype(traptypeDao.findOne((long)1));
				  acur.setOpsmposition("A-B/B-A");
				  acur.setSdate(DateUtils.getNowDate());
				  acur.setNenode(neDao.findOne((long)1));  //需改为传入
				  alarmcurrentDao.save(acur);
			}
		}		
	}
	
	/**
	 * 查询所有当前告警
	 * @return
	 */
	public List<AlarmCurrent> findAllAlarmCur(){
		List<AlarmCurrent> acurlist = (List<AlarmCurrent>)alarmcurrentDao.findAll();
		return acurlist;
	}
	
	public String acurToJson(AlarmCurrent acur){
		long neid = acur.getNenode()==null?0:acur.getNenode().getNid();
		long slotid = acur.getSlot()==null?0:acur.getSlot().getSlotid();
		List<CfgSlot> slotlist = slotDao.getCard(neid,slotid);
		CfgCard card = null;
		if (slotlist!= null && slotlist.size()>0){
			card = ((CfgSlot)slotlist.get(0)).getCard();
		}
		Map<String, Object> map = new HashMap<String, Object>();
		map.put("m_atype", acur.getAtype()==null?"":acur.getAtype().getAlarmdesc());
		map.put("m_traptype", acur.getTraptype()==null?"":acur.getTraptype().getTraptype());
		map.put("m_ip", acur.getNenode()==null?"":acur.getNenode().getIp());
		map.put("m_slot", acur.getSlot()==null?"":acur.getSlot().getNum());
		map.put("m_card", card==null?"":card.getCardname());
		map.put("m_severity", acur.getSeverity()==null?"":acur.getSeverity().getSeverity());
		map.put("m_sdate", acur.getAtime()==null?"":acur.getAtime());
		map.put("m_omode", acur.getAmode()==null?"":acur.getAmode().getOmode());
		String json = JSONObject.toJSONString(map);
		return json;
	}

	private static String getMethodName(String fname) {
		byte[] items = fname.getBytes();
		items[0] = (byte) ((char) items[0] - 'a' + 'A');
		return new String(items);
	}
	
	public List<AlarmCurrent> getAlarm(CfgNe ne) throws SnmpException{
		List<AlarmCurrent> retList = new ArrayList<AlarmCurrent>();
		snmpService.connectV2(ne.getIp(), "Admin@123");
		String curStr = snmpService.get(new SccCard(), SccCard.GetCurrentAlarm);
		if (curStr != null) {
			String[] aArr = curStr.split(",");
			String[] barr = null;
			String slotStr = "", alarmname = "", splitTemp = "", otime = "";
			Map<String, String> map = new HashMap<String, String>();
			for (int i = 1; i < aArr.length; i++) {
				map = new HashMap<String, String>();
				barr = aArr[i].split(":");
				slotStr = barr[0];
				alarmname = barr[1];
				splitTemp = slotStr + ":" + alarmname + ":";
				otime = aArr[i].replace(splitTemp, "").trim();
				String slot = slotStr.replace("Slot", "").trim();
				map.put("aname", alarmname);
				map.put("otime", otime);
				map.put("neip", ne.getIp());
				AlarmCurrent a = new AlarmCurrent();
				a.setAid(alarmname);
				a.setSlot(slotDao.findOne(new Long(slot)));
				a.setChassis(1);
				a.setPort(1);
				a.setNenode(ne);
				
				a.setSeverity(alarmseverDao.findOne(1L));//根据需要写
				
				retList.add(a);
			}
		}
		return retList;
	}
	
	public AlarmCurrent save(AlarmCurrent a ){
		return alarmcurrentDao.save(a);
	}
}
